﻿using System.Diagnostics.Contracts;
using System.Linq;
using IMModel.Domain.Common;
using System.Collections.Generic;

namespace IMModel.Domain
{
    /// <summary>
    /// Реализует вычисление объёмов градаций по умолчанию: ax = Mul(sum(B)) * b
    /// </summary>
    class DefaultGradationVolumeFunction : IVolumes<CharacteristicTerm>
    {
        public static readonly DefaultGradationVolumeFunction Instance = 
            new DefaultGradationVolumeFunction();

        /// <summary>
        /// Получает объёмы по всем градациям показателя
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sender"></param>
        /// <returns></returns>
        public virtual RespondentIndexCollection GetVolumes(IndexContext сontext,
            CharacteristicTerm contextTerm, Term sender)
        {
            Contract.Assert(сontext != null);
            Contract.Assert(contextTerm != null);
            Contract.Assert(sender != null);

            RespondentIndexCollection result = new RespondentIndexCollection();
            var a = contextTerm.Answers;

            // исходный вариант
            //foreach (var answer in a)
            //{
            //    if (answer.IsParticipantInTerm(sender))
            //        result.Add(answer.Respondent.GetMeInOtherTerm(sender), answer.Value);
            //}
            var a2 = GetFiltredAnswers(сontext, contextTerm, sender).ToArray();

            foreach (var answer in a2)
            {
                result.Add(answer.Respondent.GetMeInOtherTerm(sender), answer.Value);
            }

            var c = a2.Any()? a2.Max(x => x.GradVolume):1;
            //var c = result.Sum(x => x.Value) / result.Count;
            result /= c;

            //var coll = a.GroupBy(x => x.Respondent.GetMeInOtherTerm(sender));
            //foreach (var v in coll)
            //    result.Add(v.Key, v.Sum(x => x.Volume * x.CalcGradationWeight())
            //        / v.Sum(x => x.Volume));

            //foreach (var answer in a)
            //{
            //    if (answer.IsParticipantInTerm(sender) && !a.Any(x => x.Answer1 == answer))
            //        result.Add(answer.Respondent.GetMeInOtherTerm(sender), answer.Value);
            //}

            return result;
        }

        protected IEnumerable<Answer> GetFiltredAnswers(IndexContext сontext,
            CharacteristicTerm contextTerm, Term sender)
        {
            return contextTerm.Answers.Where(x => x.IsParticipantInTerm(sender)
                && x.LastAnswer && сontext.IndexObjectFilter(x.Respondent));
        }

        protected void Normirovanie(IEnumerable<Answer> a, RespondentIndexCollection result)
        {
            var c = a.Any() ? a.Max(x => x.GradVolume) : 1;
            result /= c;
        }
    }
}

            //var a2 = contextTerm.Answers.Where(x => x.IsParticipantInTerm(sender)
            //    && x.LastAnswer && сontext.IndexObjectFilter(x.Respondent));

            //var vols = new Dictionary<Gradation, double>();
            //double vol;
            //Gradation gr;

            //foreach (var answer in a2)
            //{
            //    foreach (var ga in answer.GradationsAnswers)
            //    {
            //        gr = ga.GradationTerm.Gradation;
            //        if (vols.ContainsKey(gr))
            //        {
            //            if (ga.Volume > vols[gr])
            //                vols[gr] = ga.Volume ?? 1;
            //        }
            //        else vols.Add(gr, ga.Volume ?? 1);
            //    }
            //}

            //foreach (var answer in a2)
            //{
            //    vol = 0;
            //    foreach (var ga in answer.GradationsAnswers)
            //    {
            //        vol *= (ga.Volume ?? 1) / vols[ga.GradationTerm.Gradation];
            //    }
            //    var w = answer.CalcGradationWeight();
            //    result.Add(answer.Respondent.GetMeInOtherTerm(sender),
            //        (vol > 0 ? vol : 1)*w);
            //}
